function [correct, f, pi_star, E, M] = alg_3_4(E, func, hyps, ks_star, M, n, n_class, Pi, size_fold, xs_star, Y, ys_actual)
% a script performing Algorithm 3.4 of R&W
% by Mark Norrish, 2011

%disp('Predicting...');

correct = 0;
mu_star = zeros(n_class,1);
Sigma = zeros(n_class);
S = 3000;
for test_ix = 1:size_fold
  mu_star = sum((Y - Pi) .* ks_star(:,:,test_ix))';
  for class = 1:n_class
    b = E(:,:,class) * ks_star(:,class,test_ix); % n * 1
    c_vec = M \ (M' \  b); % text has Rs thrown in
    for class_dash = 1:n_class
      Sigma(class, class_dash) = (E(:,:,class_dash) * c_vec)' * ks_star(:,class_dash,test_ix);
    end
    Sigma(class, class) = Sigma(class, class) + func(hyps(:,class), xs_star(test_ix,:), xs_star(test_ix,:)) - b'*ks_star(:,class,test_ix);
  end
  fudge_factor = 1e-6; % just in case
  Sigma = Sigma + fudge_factor*eye(n_class);
  try
    L = chol(Sigma);
  catch
    L = lu(Sigma);
  end
  f_star = (normrnd(zeros(S,class),ones(S,class))*L) + repmat(mu_star', S, 1);
  efs = exp(f_star);
  sefs = sum(efs')';
  pi_star = sum(efs ./ repmat(sefs, 1, class)) / S;
  
  prediction = find(pi_star == max(pi_star));
  if prediction == ys_actual(test_ix)
    correct = correct+1;
  else
    %fprintf('A data point near %f, %f was supposed to be %i but was misclassified as %i. \n', xs_star(test_ix,:)', ys_actual(test_ix), prediction); % kludge alert
  end
end